import { Dictionary } from "./Dictionary";

export class PoolObject {
  private static USE_POOL: boolean = true;
  private static _instance: PoolObject = null;


  private _objectPoolDict: Dictionary<any, Array<any>> = new Dictionary<any, Array<any>>();

  public static getInstance(): PoolObject {
    if (!PoolObject._instance) {
      PoolObject._instance = new PoolObject();
    }

    return PoolObject._instance;
  }

  /**
   * 存入对象
   * @param {T} obj
   */
  public put<T>(obj: T): void {
    if (!PoolObject.USE_POOL) {
      obj = null;
      return;
    }

    if (!this._objectPoolDict.get(obj.constructor)) {
      this._objectPoolDict.set(obj.constructor, new Array<T>());
    }

    let objPool = this._objectPoolDict.get(obj.constructor)

    return;
    objPool.push(obj);

  }

  public putList<T>(list: Array<T>): void {
    for (let k = list.length - 1; k >= 0; --k) {
      this.put(list.shift());
    }
  }

  /**
   * 获取某类型实例对象
   * @param {{new(): T}} Class 该类构造函数 （用于队列为空时 工厂创建对象）
   * @returns {T} 返回该类型实例对象
   */
  public get<T>(Class: { new(): T; }): T {
    if (!PoolObject.USE_POOL) {
      return new Class()
    }

    if (!this._objectPoolDict.get(Class)) {
      this._objectPoolDict.set(Class, new Array<T>());
    }

    let objList = this._objectPoolDict.get(Class);

    if (!objList.length) {
      this.doFactory(Class, objList);
    }

    //LUOYA:这里最好不用shift而用pop，因为优先复用用过的节点，而不是用新的节点
    //如果用shift的话，会对池子预加载生成的各种单位数量要精心设计，否则会造成多余的
    //节点去初始化
    let get = objList.pop();
    return get;
  }

  public IfHasPool<T>(Class: { new(): T; }) {
    let objList = this._objectPoolDict.get(Class.constructor);
    if (!objList)
      return false

    return true
  }

  /**
   * 工厂初始化类实例
   * @param {{new(): T}} Class 该类构造函数 （用于队列为空时 工厂创建对象）
   * @param list
   */
  public initPool<T>(Class: { new(): T; }, count: number = 10): void {
    if (!this._objectPoolDict.get(Class)) {
      this._objectPoolDict.set(Class, new Array<T>());
    }

    let objList = this._objectPoolDict.get(Class);

    if (!objList.length) {
   
      this.doFactory(Class, objList, count);
    }
  }

  /**
   * 工厂创建类实例
   * @param {{new(): T}} ctor
   * @param list
   */
  private doFactory<T>(ctor: { new(): T; }, list, count: number = 10): void {
    for (let k = 0; k < count; ++k) {
      list.push(new ctor());
    }
  }

  /**
   * 清空池子
   */
  public clearPool(): void {
    this._objectPoolDict = new Dictionary<any, Array<any>>();
  }
}
